import * as THREE from 'three';
import { getColorTable, getShaderCode } from './utils';

export default class PointsMaterial extends THREE.RawShaderMaterial {
  option = { hasIntensity: false, hasRGB: false, hasVelocity: false };
  constructor() {
    super({
      uniforms: {
        heightRange: {
            value: new THREE.Vector2(-10000, 10000),
        },
        pointHeight: {
            value: new THREE.Vector2(-10000, 10000),
        },
        pointVelocity: {
            value: new THREE.Vector2(-10000, 10000),
        },
        pointSize: { value: 1 },
        trimType: { value: 1.0 },
        colorMode: { value: -1 },
        colorRoad: { value: -1 },
        intensityRange: { value: new THREE.Vector2(0, 255) },
        velocityRange: { value: new THREE.Vector2() },
        brightness: { value: 1 },
        // filter
        hasFilterBox: { value: -1 },
        boxInfo: {
            value: {
                // 0 color, 1 color filter,
                type: 0,
                min: new THREE.Vector3(-10, -10, -5),
                max: new THREE.Vector3(10, 10, 5),
                color: new THREE.Color(1, 1, 0),
                matrix: new THREE.Matrix4(),
            },
        },
        edgeColor: {
            value: ['#000dff', '#ff0000'].map((color) => new THREE.Color(color)),
        },
        singleColor: {
            value: new THREE.Color('#87abff'),
        },
        colorTable: {
            value: getColorTable(),
        },
        openIntensity: {
            value: -1,
        },
        hasCameraRegion: { value: -1 },
        regionMatrix: { value: new THREE.Matrix4() },
      },
      vertexShader: '',
      fragmentShader: '',
    })
    this.updateShader();
  }
  updateShader() {
    let { vertex, frag } = getShaderCode(this.option);
    this.vertexShader = vertex;
    this.fragmentShader = frag;
    this.needsUpdate = true;
  }
  setUniforms(option) {
    let keys = Object.keys(option);
    let uniforms = this.uniforms;
    keys.forEach((key) => {
      switch (key) {
        case 'boxInfo':
          Object.assign(uniforms[key].value, option[key]);
          break;
        case 'singleColor':
          uniforms.singleColor.value.set(option.singleColor);
          break;
        case 'edgeColor':
          option.edgeColor?.forEach((color, index) => {
            uniforms.edgeColor.value[index].set(color);
          });
          break;
        default:
          uniforms[key].value = option[key];
      }
    });
  }
}